package org.zoomdev.zoom.dao.transaction;

import org.zoomdev.zoom.common.io.Io;
import org.zoomdev.zoom.dao.DaoException;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

class Transaction {
    final DataSource ds;
    private final int level;
    private Integer oldLevel;
    private Connection connection;

    Transaction(int level, DataSource ds) {
        this.ds = ds;
        this.level = level;
    }


    /**
     * 当启用事务处理的时候修改
     *
     * @throws SQLException
     */
    Connection getConnection() {
        Connection connection = this.connection;
        if (connection != null) {
            return connection;
        }
        try {
            connection = ds.getConnection();
            connection.setAutoCommit(false);
            int oldLevel = connection.getTransactionIsolation();
            if (oldLevel != level) {
                connection.setTransactionIsolation(level);
                this.oldLevel = oldLevel;
            }
            this.connection = connection;
            return connection;
        } catch (SQLException e) {
            throw new DaoException("获取数据库连接失败", e);
        }
    }


    void commit() {
        final Connection connection = this.connection;
        if (connection == null) {
            return;
        }
        final Integer oldLevel = this.oldLevel;
        try {
            connection.commit();
        } catch (SQLException e) {
            throw new DaoException("事务处理commit失败", e);
        } finally {
            try {
                connection.setAutoCommit(true);
                if (oldLevel != null) {
                    connection.setTransactionIsolation(oldLevel);
                    this.oldLevel = null;
                }
            } catch (SQLException e) {
                throw new DaoException("事务处理commit之后设置失败", e);
            } finally {
                releaseConnection();
            }
        }
    }

    void releaseConnection() {
        final Connection connection = this.connection;
        if (connection != null) {
            Io.close(connection);
            this.connection = null;
        }
    }

    void rollback() {
        final Connection connection = this.connection;
        if (connection == null) {
            return;
        }

        final Integer oldLevel = this.oldLevel;
        try {
            connection.rollback();
        } catch (SQLException e) {
            throw new DaoException("事务处理rollback失败", e);
        } finally {
            try {
                connection.setAutoCommit(true);
                if (oldLevel != null) {
                    connection.setTransactionIsolation(oldLevel);
                    this.oldLevel = null;
                }
            } catch (SQLException e) {
                throw new DaoException("事务处理rollback之后设置", e);
            } finally {
                releaseConnection();
            }
        }
    }

}
